#include <iostream>
#include <mutex>
#include <thread>

using std::cout;
using std::endl;
using std::mutex;
using std::thread;

// 1: std::mutex
mutex mtx1;
int gCnt = 0;

void threadFunc1()
{
    for(size_t idx = 0; idx != 1000000; ++idx)
    {
        mtx1.lock();
        ++gCnt;
        mtx1.unlock();
    }
}

void test1(){
    thread thA(threadFunc1);
    thread thB(threadFunc1);

    thA.join();
    thB.join();

    cout << "gCnt = " << gCnt << endl;
}

// 2: std::lock_guard
mutex mtx2;

void threadFunc2()
{
    for(size_t idx = 0; idx != 1000000; ++idx)
    {
        std::lock_guard<mutex> lg(mtx2);
        ++gCnt;
    }
}

void test2(){
    thread thA(threadFunc2);
    thread thB(threadFunc2);

    thA.join();
    thB.join();

    cout << "gCnt = " << gCnt << endl;
}

// 3: std::unique_lock
mutex mtx3;

void threadFunc3()
{
    for(size_t idx = 0; idx != 1000000; ++idx)
    {
        std::lock_guard<mutex> ul(mtx3);
        ++gCnt;
    }
}

void test3(){
    thread thA(threadFunc3);
    thread thB(threadFunc3);

    thA.join();
    thB.join();

    cout << "gCnt = " << gCnt << endl;
}

int main()
{
    test1();
    test2();
    test3();
    return 0;
}

